#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using PrisonDefence.Models;
using PrisonDefence.Components;
using Prison.Defence.Content.Pipleline.DataTypes;
#endregion

namespace PrisonDefence.GameStateManagement
{
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    class GameplayScreen : GameScreen
    {
        #region Fields

        ContentManager content;
        SpriteFont gameFont;

        Random random = new Random();

        World world;

        Map map;
        Level level;

        float pauseAlpha;

        CameraComponent cameraComponent;
        Vector2 cursorPos;

        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
        }


        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            SceneDefinition sceneDef = content.Load<SceneDefinition>("Levels/LevelDesc1");

            world = new World();
            world.LoadContent(ScreenManager.GraphicsDevice, content, sceneDef);

            gameFont = content.Load<SpriteFont>("fonts/gamefont");

            // A real game would probably have more content than this sample, so
            // it would take longer to load. We simulate that by delaying for a
            // while, giving you a chance to admire the beautiful loading screen.
            map = new Map(content.Load<Texture2D>("levels/level1"));

            level = new Level(map, null, new BasicEffect(ScreenManager.GraphicsDevice));

            //float aspectRatio = ScreenManager.GraphicsDevice.Viewport.AspectRatio;
            //Matrix view = Matrix.CreateLookAt(new Vector3(64.0f, 32.0f, -64.0f), new Vector3(64.0f, 32.0f, 32f), Vector3.Up);

            //Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f);
            cameraComponent = new CameraComponent(ScreenManager.Game, ScreenManager.Camera);
            ScreenManager.Camera.Move(64.0f, 32.0f, 0.0f);
            ScreenManager.Camera.LookAt(new Vector3(64.0f, 32.0f, 32f));
            ScreenManager.Camera.CurrentBehavior = Camera.Behavior.Orbit;


            // once the load has finished, we use ResetElapsedTime to tell the game's
            // timing mechanism that we have just finished a very long frame, and that
            // it should not try to catch up.
            ScreenManager.Game.ResetElapsedTime();
        }


        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void UnloadContent()
        {
            content.Unload();
        }


        #endregion

        #region Update and Draw


        /// <summary>
        /// Updates the state of the game. This method checks the GameScreen.IsActive
        /// property, so the game will stop updating when the pause menu is active,
        /// or if you tab away to a different application.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, false);

            // Gradually fade in or out depending on whether we are covered by the pause screen.
            if (coveredByOtherScreen)
                pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
            else
                pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);

            if (IsActive)
            {
                UpdateActive(gameTime);
            }
        }


        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(InputComponent input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            // Look up inputs for the active player profile.
            int playerIndex = (int)ControllingPlayer.Value;

            KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
            GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];

            cursorPos = input.GetCursorPosition(ControllingPlayer);

            // The game pauses either if the user presses the pause button, or if
            // they unplug the active gamepad. This requires us to keep track of
            // whether a gamepad was ever plugged in, because we don't want to pause
            // on PC if they are playing with a keyboard and have no gamepad at all!
            bool gamePadDisconnected = !gamePadState.IsConnected &&
                                       input.GamePadWasConnected[playerIndex];

            if (input.IsPauseGame(ControllingPlayer) || gamePadDisconnected)
            {
                ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer);
            }
            else
            {

            }
        }


        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            // This game has a blue background. Why? Because!
            //ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
            //                                   Color.CornflowerBlue, 0, 0);
            ScreenManager.GraphicsDevice.Clear(Color.Black);

            DrawScene(gameTime);

            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0 || pauseAlpha > 0)
            {
                float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);

                ScreenManager.FadeBackBufferToBlack(alpha);
            }
        }

        private void UpdateActive(GameTime gameTime)
        {
            cameraComponent.Update(ScreenManager.Input, gameTime);
            world.Update(gameTime);
            level.Update(gameTime);
        }

        private void DrawScene(GameTime gameTime)
        {
            world.Draw(ScreenManager.GraphicsDevice, gameTime, ScreenManager.Camera.Position, ScreenManager.Camera.ViewMatrix, ScreenManager.Camera.ProjectionMatrix);

            //level.Draw(ScreenManager.GraphicsDevice, gameTime, ScreenManager.Camera.ViewMatrix, ScreenManager.Camera.ProjectionMatrix);

            if (IsActive)
            {
                SpriteBatch spriteBatch = ScreenManager.SpriteBatch;

                spriteBatch.Begin();

                spriteBatch.Draw(ScreenManager.Cursor, cursorPos, Color.White);

                spriteBatch.End();
            }
        }


        #endregion
    }
}
